/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package Raytracing.BRDF;

import Raytracing.FresnelDielectric;
import Raytracing.Ray;
import processing.core.PVector;

/**
 *
 * @author Matt
 */
public class SpecularTransmissionBRDF implements BRDF {

    PVector T;
    FresnelDielectric fresnel;

    public SpecularTransmissionBRDF(FresnelDielectric fresnel, PVector T) {
        this.fresnel = fresnel;
        this.T = T;
    }

    public PVector getReflectance(PVector incoming, PVector outgoing, PVector normal, float tu, float tv, PVector u, PVector v) {

        return new PVector(0, 0, 0);

    }

    public float sampleReflectance(PVector outgoing, Ray sample,
            PVector normal, PVector BRDF,
            float tu, float tv, PVector u, PVector v,
            float u1, float u2) {


        boolean entering = false;
        if (cosTheta(outgoing) > 0) {
            entering = true;
        }

        float ei = fresnel.etai;
        float et = fresnel.etat;

        if (entering == false) {
            ei = fresnel.etat;
            et = fresnel.etai;
        }

        float sini2 = sinTheta2(outgoing);
        float eta = ei / et;
        float sint2 = eta * eta * sini2;
        //total internal reflection
        BRDF.set(T);
        if (sint2 > 1.f) {
            BRDF.set(0, 0, 0);

        }

        float cost = (float) (Math.sqrt(Math.max(0, 1.f - sint2)));
        if (entering) {
            cost = -cost;
        }
        float sintOverSini = eta;


        sample.direction.x = sintOverSini * -outgoing.x;
        sample.direction.y = sintOverSini * -outgoing.y;
        sample.direction.z = cost;

        PVector F = fresnel.getFresnel(cosTheta(outgoing));
        
        F.x = 1.f - F.x;
        F.y = 1.f - F.y;
        F.z = 1.f - F.z;


        
        BRDF.mult((ei * ei) / (et * et));

        BRDF.mult(F);
        sample.bounceType = Ray.SPECULAR;
        return 1f;
    }

    public float cosTheta(PVector vec) {
        return vec.z;
    }

    public float sinTheta2(PVector vec) {
        return 1.f - (vec.z * vec.z);
    }
}
